#include "../include/LRUCache.h"

LRUCache::LRUCache(int capacity)
:_capacity(capacity)
,_size(0)
{
    _head = new CacheNode;
    _last = new CacheNode;
    _head->next = _last;
    _last->prev = _head;
}

vector<string> LRUCache::JsonToV(string mes)
{
    auto js = json::parse(mes);
    string tmp;
    tmp = js["message"];
    auto js1 = json::parse(tmp);
    return js1["keywords"];
}
string LRUCache::VtoJson(vector<string> vec)
{
    json j;
    j["message"] = vec;
    return j.dump();
}
bool LRUCache::search(string key)
{
    if(!_keyMap.count(key)||_keyMap[key]==nullptr)
    {
        return false;
    }
    else
    {
        return true;
    }
}

void LRUCache::addPendingELement(const string &key,const vector<string> &value)
{
    string val = VtoJson(value);
    put(key, val);
}

string LRUCache::get(string key)
{
     if(!_keyMap.count(key)||_keyMap[key]==nullptr)
        return {"no exit"};

    //类外先使用search判断是否存在
    CacheNode *cur = _keyMap[key];

    //取出结点
    cur->prev->next = cur->next;
    cur->next->prev = cur->prev;
    //将结点放到链队头部，表示最近使用过一次
    cur->next = _head->next;
    _head->next = cur;
    cur->next->prev = cur;
    cur->prev = _head;
    //返回其值
    json msgJson;
    msgJson["keywords"] = cur->data;
    return msgJson.dump();
}

void LRUCache::put(string key,string val)
{
    vector<string> value = JsonToV(val);
    // 如果存在
    if(_keyMap.count(key)&&_keyMap[key]!=nullptr)
    {
        _keyMap[key]->data = value;//修改其值
        get(key);//插入队头；
    }
    else//如果不存在
    {
        //创建新节点
        CacheNode *newNode = new CacheNode;
        _keyMap[key] = newNode;
        newNode->data = value;
        newNode->key = key;
        //插入队头
        newNode->next = _head->next;
        _head->next = newNode;
        newNode->next->prev = newNode;
        newNode->prev = _head;
        _size++;
        //如果大于容量
        if(_size>_capacity)
        {
            //摘除尾部结点
            CacheNode *del = _last->prev;

            del->prev->next = del->next;
            del->next->prev = del->prev;

            //在两个表中都删除
            _keyMap.erase(del->key);
            delete del;
            _size--;
        }
    }
}

void LRUCache::mergePending(const LRUCache &rhs)
{
    for(auto &x:rhs._keyMap)
    {
        string val = VtoJson(x.second->data);
        put(x.first, val);
    }
}

void LRUCache::readFromFile(const string &filename)
{
    ifstream ifs(filename);
    if(!ifs.good())
    {
        perror("LRUCache::readFromFile : ifs ERROR");
        return;
    }
    string line;
    string value;
    while(ifs >> value && getline(ifs, line))
    {
        vector<string> vec;
        string word;
        std::istringstream iss(line);
        while(iss>>word)
        {
            vec.push_back(word);
        }
        string val = VtoJson(vec);
        put(value, val);
    }
    ifs.close();
}

void LRUCache::writeToFile(const string &filename)
{
    ofstream ofs(filename, ios::out | ios::app);
    if(!ofs.good())
    {
        perror("LRUCache::writeToFile : ofs ERROR");
    }

    for(auto &key:_keyMap)
    {
        ofs << key.first << " ";
        for(auto &value:key.second->data)
        {
            ofs << value << " ";
        }
        ofs << endl;
    }
    ofs.close();
}

void LRUCache::update(const LRUCache &rhs)
{
    for(auto &Map:rhs._keyMap)
    {
        string key = Map.first;
        vector<string> vec = Map.second->data;
        string val = VtoJson(vec);
        put(key, val);
    }
}

LRUCache& LRUCache::getPendingList()
{
    return *this;
}